﻿using CTP.CRM.Core.Common.Dto;
using CTP.CRM.Core.Common.SharedModel.Pub;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc.Authorization;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Primitives;
using Volo.Abp;
using CTP.CRM.Core.SharedModel.Enums;

namespace CTP.CRM.Core.SharedModel.Pub
{
    public class ApiAsyncAuthorizationFilter : Attribute, IAsyncAuthorizationFilter, IFilterMetadata
    {
        private const string AbpDetectorController = "AbpApiDefinitionController.";

        public Task OnAuthorizationAsync(AuthorizationFilterContext context)
        {
            Endpoint endpoint = context?.HttpContext?.GetEndpoint();
            if (endpoint.DisplayName.Contains("AbpApiDefinitionController.") || IsSystemRequest() || HasAllowAnonymous(context, endpoint))
            {
                return Task.CompletedTask;
            }

            string text = context.HttpContext.Request.Path;
            if (text == "/OAuth/RefreshToken" || text == "/ExternalUser/RefreshToken")
            {
                return Task.CompletedTask;
            }

            ExecuteAuthentication(context);
            return Task.CompletedTask;
            static bool IsSystemRequest()
            {
                return !string.IsNullOrEmpty(CTPABPCore.HttpContext.Request.Headers["SystemRequest"]);
            }
        }

        //
        // 摘要:
        //     Checks if the provided context or endpoint allows anonymous access.
        //
        // 参数:
        //   context:
        //     The authorization filter context.
        //
        //   endpoint:
        //     The endpoint to check for anonymous access metadata.
        //
        // 返回结果:
        //     True if anonymous access is allowed, otherwise false.
        private static bool HasAllowAnonymous(AuthorizationFilterContext context, Endpoint endpoint)
        {
            foreach (IFilterMetadata filter in context.Filters)
            {
                if (filter is IAllowAnonymousFilter)
                {
                    return true;
                }
            }

            return endpoint?.Metadata?.GetMetadata<IAllowAnonymous>() != null;
        }

        private static void ExecuteAuthentication(AuthorizationFilterContext context)
        {
            StringValues authorization = context.HttpContext.Request.Headers.Authorization;
            if (string.IsNullOrEmpty(authorization))
            {
                context.Result = new JsonResult(new UnifyResultDto("401", "未找到鉴权凭证", null));
                return;
            }

            try
            {
                ReqHeaderResolveHelper.VerfiyToken(authorization);
                context.HttpContext.Request.Headers["TokenOrigin"] = TokenOrigin.内部用户.ToString();
            }
            catch (BusinessException ex)
            {
                context.Result = new JsonResult(new UnifyResultDto(ex.Code, ex.Message, null));
            }
            catch (Exception ex2)
            {
                context.Result = new JsonResult(new UnifyResultDto("500", ex2.Message, null));
            }
        }
    }
}
